package com.dhcc.DRGsHosp.facade.impl;

import com.dhcc.DRGsHosp.application.ClinicGroupApplication;
import com.dhcc.DRGsHosp.core.domain.ClinicGroup;
import com.dhcc.DRGsHosp.facade.ClinicGroupFacade;
import com.dhcc.DRGsHosp.facade.DepartmentFacade;
import com.dhcc.DRGsHosp.facade.FileUploadFacade;
import com.dhcc.DRGsHosp.facade.dto.ClinicGroupDTO;
import com.dhcc.DRGsHosp.facade.dto.DepartmentDTO;
import com.dhcc.DRGsHosp.facade.impl.assembler.ClinicGroupAssembler;
import com.dhcc.DRGsHosp.infra.util.DrgsIndex;
import com.dhcc.DRGsHosp.infra.util.StringUtils;
import org.dayatang.domain.InstanceFactory;
import org.dayatang.querychannel.QueryChannelService;
import org.dayatang.utils.Page;
import org.openkoala.koala.commons.InvokeResult;

import javax.inject.Inject;
import javax.inject.Named;
import java.lang.reflect.Field;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Named("drgsFacadeImplchl2017051101")
public class ClinicGroupFacadeImpl implements ClinicGroupFacade {

	@Inject
	private ClinicGroupApplication  application;
	@Inject
	private DepartmentFacade  departmentFacade;
	@Inject
	private FileUploadFacade  fileUploadFacade;
	
	private QueryChannelService queryChannel;

    private QueryChannelService getQueryChannelService(){
       if(queryChannel==null){
          queryChannel = InstanceFactory.getInstance(QueryChannelService.class,"queryChannel");
       }
     return queryChannel;
    }
	
	public InvokeResult getClinicGroup(Long id) {
		return InvokeResult.success(ClinicGroupAssembler.toDTO(application.getClinicGroup(id)));
	}
	
	public InvokeResult saveClinicGroup(Map<String,Object> json) {
		// 查询科室所在科室组
		String depCode = json.get("parDepCode") != null ? (String)(json.get("parDepCode")):"" ;
		String depGroupCode = "" ;
		if(StringUtils.hasLength(depCode)) {
			String[] depCodea = depCode.split(",") ;
			for(String s : depCodea) {
				DepartmentDTO departmentDto = departmentFacade.findDepartmentByDepCode(s) ;
				if( departmentDto != null ) {
					depGroupCode += departmentDto.getParDepGroupCode() + "," ;
				}
			}
		}
		if (StringUtils.hasLength(depGroupCode)) {
			depGroupCode = depGroupCode.substring(0, depGroupCode.lastIndexOf(",")) ;
		}
		json.put("parDepGroupCode", depGroupCode) ;
		application.saveClinicGroup(json) ;
		return InvokeResult.success();
	}
	
	public InvokeResult removeClinicGroup(String id) {
		ClinicGroup doct=new ClinicGroup();
		doct.setId(id);
		application.removeClinicGroup(doct);
		return InvokeResult.success();
	}
	
	public InvokeResult removeClinicGroups(String[] ids) {
		for (String id : ids) {
			ClinicGroup doct=new ClinicGroup();
			doct.setId(id);
			application.removeClinicGroup(doct) ;
		}
		return InvokeResult.success();
	}
	
	public List<ClinicGroupDTO> findAllClinicGroup() {
		return ClinicGroupAssembler.toDTOs(application.findAllClinicGroup());
	}
	
	public Page<ClinicGroupDTO> pageQueryClinicGroup(ClinicGroupDTO queryVo, int currentPage, int pageSize) {
		List<Object> conditionVals = new ArrayList<Object>();
	   	StringBuilder sql = new StringBuilder("") ;
	   	sql.append("select cc.id ,cc.group_code ,cc.group_name,cc.group_type, ") ;
	   	sql.append("cc.parward_code,cc.pardep_code,cc.group_active,cc.group_order,dep.dep_name,ward.ward_desc,dd.dic_desc ") ;
	   	sql.append(" from  drgs.t_clinicgroup cc \n") ;
	   	sql.append("left join drgs.t_ward ward \n") ;
	   	sql.append("on cc.parward_code = ward.ward_code \n") ;
	   	sql.append("left join drgs.t_department dep \n") ;
	   	sql.append("on dep.dep_code = cc.pardep_code \n") ;
	   	sql.append("left join drgs.mr_dictionarydata dd \n") ;
	   	sql.append("on dd.dic_value = cc.group_type and dd.dic_code = 'DOCTOR_TYPE' \n") ;
	   	sql.append("where 1=1 ") ;
	   	if (queryVo.getGroupName() != null && !"".equals(queryVo.getGroupName())) {
	   		sql.append("and cc.group_name like ? ");
	   		conditionVals.add(MessageFormat.format("%{0}%", queryVo.getGroupName()));
	   	}		
	   	if (queryVo.getParDepCode() != null && !"".equals(queryVo.getParDepCode())) {
	   		sql.append("and cc.pardep_code = ? ");
	   		conditionVals.add(MessageFormat.format("{0}", queryVo.getParDepCode()));
	   	}	
	   	if (queryVo.getParWardCode() != null && !"".equals(queryVo.getParWardCode())) {
	   		sql.append(" and cc.parward_code = ? ");
	   		conditionVals.add(MessageFormat.format("{0}", queryVo.getParWardCode()));
	   	} 
	   	sql.append(" order by to_number(cc.group_order) ") ;
	   	
        @SuppressWarnings("unchecked")
		Page<Object[]> pages = getQueryChannelService()
		   .createSqlQuery(sql.toString())
		   .setParameters(conditionVals)
		   .setPage(currentPage, pageSize)
		   .pagedList() ;
        List<Object[]> clinicGroupList = pages.getData() ;
        List<ClinicGroupDTO> clinicGroupDTOList = new ArrayList<>() ;
        if(clinicGroupList!=null) {
        	for(Object[] obj : clinicGroupList) {
        		ClinicGroupDTO clinicGroupDTO = new ClinicGroupDTO() ;
        		clinicGroupDTO.setId(obj[0] != null ? (obj[0]).toString() : "");
        		clinicGroupDTO.setGroupCode(obj[1] != null ? (String)obj[1] : "");
        		clinicGroupDTO.setGroupName(obj[2] != null ? (String)obj[2] : "");
        		clinicGroupDTO.setGroupType(obj[3] != null ? (String)obj[3] : "");
        		clinicGroupDTO.setParWardCode(obj[4] != null ? (String)obj[4] : "");
        		clinicGroupDTO.setParDepCode(obj[5] != null ? (String)obj[5] : "");
        		clinicGroupDTO.setGroupActive(Integer.parseInt(obj[6] != null ? (obj[6]).toString() : "0"));
        		clinicGroupDTO.setGroupOrder(obj[7] != null ? (obj[7]).toString() : "");
        		clinicGroupDTO.setParDepName(obj[8] != null ? (String)obj[8] : "");
        		clinicGroupDTO.setParWardDesc(obj[9] != null ? (String)obj[9] : "");
        		clinicGroupDTO.setGroupTypeDesc(obj[10] != null ? (String)obj[10] : "");
        		clinicGroupDTOList.add(clinicGroupDTO) ;
        	}
        }
        return new Page<ClinicGroupDTO>(pages.getStart(), pages.getResultCount(),pageSize, clinicGroupDTOList) ;
	}

	/* (non-Javadoc)
	 * @see com.dhcc.DRGsHosp.facade.ClinicGroupFacade#findAllClinicGroup(com.dhcc.DRGsHosp.facade.dto.ClinicGroupDTO)
	 */
	@Override
	public Object findAllClinicGroup(ClinicGroupDTO dto) {
		// TODO Auto-generated method stub
		return application.findAllClinicGroup(ClinicGroupAssembler.toEntity(dto));
	}


	@Override
	public Boolean isGroupCodeExist(String groupCode) {
		return application.isGroupCodeExist(groupCode);
	}

	@Override
	public boolean isGroupOrderExist(String groupOrder, String groupCode) {
		return application.isGroupOrderExist(groupOrder, groupCode)  ;
	}

	@Override
	public List<Map<String,Object>> findCaseCntDocCodeIsNull(String dateFrom, String dateTo) {
		dateFrom = DrgsIndex.formateDateFrom(dateFrom) ;
		dateTo = DrgsIndex.formateDateTo(dateTo) ;
		StringBuffer sql = new StringBuffer() ;
		sql.append(" select yearandmonth,count(distinct pmainindex) casecnt, \n") ;
		sql.append(" COUNT(distinct doc1) depmaster,COUNT(distinct doc2) protomedicus,COUNT(distinct doc3) physician,COUNT(distinct doc4) resident,COUNT(distinct doc5) clinic ,COUNT(distinct doc6) operator ,COUNT(distinct doc7) assistone,COUNT(distinct doc8) assisttwo from ( \n") ;
		sql.append(" select to_char(ipinfo.p00290000,'yyyy-mm') yearandmonth ,  ipinfo.pmainindex ,  \n") ;
		sql.append(" decode(ipinfo.p00600101,null,ipinfo.pmainindex,null) doc1, decode(ipinfo.p00600201,null,ipinfo.pmainindex,null) doc2 , decode(ipinfo.p00600301,null,ipinfo.pmainindex,null) doc3, \n") ;
		sql.append(" decode(ipinfo.p00600401,null,ipinfo.pmainindex,null) doc4, decode(ipinfo.P00601001,null,ipinfo.pmainindex,null) doc5 , \n") ;
		sql.append(" decode(operation.po0401,null,operation.pmainindex,null) doc6, decode(operation.po0501,null,operation.pmainindex,null) doc7 , decode(operation.po0601,null,operation.pmainindex,null) doc8 \n") ;
		sql.append(" from drgs.mr_ipinfo ipinfo \n") ;
		sql.append("  left join drgs.mr_operation operation on ipinfo.pmainindex = operation.pmainindex \n") ;
		sql.append(" where to_char(ipinfo.p00290000,'yyyy-mm-dd') between :dateFrom and :dateTo \n") ;
		sql.append(" and ((ipinfo.P00600101 is null and ipinfo.P00600100 is not null) or (ipinfo.p00600201 is null and ipinfo.P00600200 is not null)  or (ipinfo.p00600301 is null and ipinfo.P00600300 is not null)  or (ipinfo.p00600401 is null and ipinfo.P00600400 is not null) or (ipinfo.p00601001 is null and ipinfo.p00601000 is not null) or (operation.po0401 is null and operation.po0400 is not null) or (operation.po0501 is null and operation.po0500 is not null)  or (operation.po0601 is null and operation.po0600 is not null)) \n") ;
		sql.append(" )a group by yearandmonth order by yearandmonth desc \n") ;
		Map<String, Object> params = new HashMap<>() ;
		params.put("dateFrom", dateFrom) ;
		params.put("dateTo", dateTo) ;
		return application.findCaseCntDocCodeIsNull(sql.toString(), params);
	}

	@Override
	public void keepIpinfoAndClinicGroup(String dateFrom, String dateTo) {
		dateFrom = DrgsIndex.formateDateFrom(dateFrom) ;
		dateTo = DrgsIndex.formateDateTo(dateTo) ;
		/**
		 * 加载医师相关信息
		 */
		List<ClinicGroup> doctorList = application.findAllClinicGroup();
		Map<String, Object> docDescMap = new HashMap<>();//医师map 医师名称->医师code
		Map<String, Object> docCodeMap = new HashMap<>();//医师map 医师code->医师名称
		//01:科主任 02:主任（副主任）医师  03:主治医师 04:住院医师 05:主诊医师 06:进修医师 07:研究生实习医师 08:实习医师 09:质控医师
		for (ClinicGroup cg : doctorList) {
			docDescMap.put(cg.getGroupName(),cg.getGroupCode());
			docCodeMap.put(cg.getGroupCode(),cg.getGroupName());
		}
		
		// 处理首页医师信息
		Map<String,String> sqlCondition = new HashMap<>() ;
		sqlCondition.put("dateFrom", dateFrom) ;
		sqlCondition.put("dateTo", dateTo) ;
		sqlCondition.put("code", "p00600101") ;
		sqlCondition.put("desc", "p00600100") ;
		Map<String,Object> initMap = new HashMap<>() ;
		initMap.put("docDescMap", docDescMap) ;
		initMap.put("docCodeMap", docCodeMap) ;
		processDoctorCode (sqlCondition,initMap,"MrIpInfo") ;
		
		sqlCondition.put("code", "p00600201") ;
		sqlCondition.put("desc", "p00600200") ;
		processDoctorCode (sqlCondition,initMap,"MrIpInfo") ;
		
		sqlCondition.put("code", "p00600301") ;
		sqlCondition.put("desc", "p00600300") ;
		processDoctorCode (sqlCondition,initMap,"MrIpInfo") ;
		
		sqlCondition.put("code", "p00600401") ;
		sqlCondition.put("desc", "p00600400") ;
		processDoctorCode (sqlCondition,initMap,"MrIpInfo") ;
		
		sqlCondition.put("code", "p00601001") ;
		sqlCondition.put("desc", "p00601000") ;
		processDoctorCode (sqlCondition,initMap,"MrIpInfo") ;
		
//		// 处理手术医师信息
		sqlCondition.put("code", "po0401") ;
		sqlCondition.put("desc", "po0400") ;
		processDoctorCode (sqlCondition,initMap,"MrOperation") ;
		sqlCondition.put("code", "po0501") ;
		sqlCondition.put("desc", "po0500") ;
		processDoctorCode (sqlCondition,initMap,"MrOperation") ;
		sqlCondition.put("code", "po0601") ;
		sqlCondition.put("desc", "po0600") ;
		processDoctorCode (sqlCondition,initMap,"MrOperation") ;
	}
	
	
	/**
	 *  通过反射赋值
	 *  setProperty.  
	 *  @Description：
	 *  @Author ChenHanlin
	 *  @param obj
	 *  @param propertyName
	 *  @param value
	 *  @throws Exception 
	 *  @Date:2018年3月12日下午2:28:06
	 */
	private void setProperty(Object obj, String propertyName, Object value) {
        Class clazz=obj.getClass();   //获取字节码对象
        Field field;
		try {
			field = clazz.getDeclaredField(propertyName);
			field.setAccessible(true); //设置访问权限
	        field.set(obj,value);   //设置值
		} catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
			e.printStackTrace();
		} 
        
    }
	
	/**
	 *  处理医师编码
	 *  processDoctorCode.  
	 *  @Description：
	 *  @Author ChenHanlin
	 *  @param sqlCondition 参数条件
	 *  @param initMap 医师信息
	 *  @param entityClass 实体类(住院信息表、手术表)
	 *  @Date:2018年3月12日下午4:56:27
	 */
	private void processDoctorCode (Map<String,String> sqlCondition,Map<String,Object> initMap,String entityClass) {
		String code = sqlCondition.get("code") ;
		String desc = sqlCondition.get("desc") ;
		String dateFrom = sqlCondition.get("dateFrom") ;
		String dateTo = sqlCondition.get("dateTo") ;
		String sql = findSqlByDocField(code,desc,dateFrom,dateTo,entityClass) ;
		List<Map<String,Object>> resultList = application.excuteQuery(sql, new HashMap<String,Object>()) ;
		for(Map<String,Object> map:resultList) {
			 Class<?> clazz = null;
			 Object obj = new Object();
			 Map<String, String> docResultMap = new HashMap<>();
			 String pmainindex = map.get("ID") == null ? "" :map.get("ID").toString()  ;
			 String doccode = map.get("DOCCODE") == null ? "" :map.get("DOCCODE").toString()  ;
			 String docname = map.get("DOCNAME") == null ? "" :map.get("DOCNAME").toString()  ;
			try {
				clazz = Class.forName("com.dhcc.DRGsHosp.core.domain."+entityClass);
				//使用clazz默认构造器创建对象
				obj = clazz.newInstance();
				if("MrIpInfo".equals(entityClass)){
					Map<String,String> mapObj = new HashMap<>() ;
					mapObj.put("code",doccode) ;
					mapObj.put("desc",docname) ;
					docResultMap = fileUploadFacade.processCodeAndDesc(mapObj,(Map<String,Object>)initMap.get("docCodeMap"),(Map<String,Object>)initMap.get("docDescMap"),"doctor");
					setProperty(obj, code, docResultMap.get("code"));
					setProperty(obj, desc, docResultMap.get("desc"));
					setProperty(obj, "pmainIndex", pmainindex);
				} else if("MrOperation".equals(entityClass)) {
					Map<String,String> mapObj = new HashMap<>() ;
					mapObj.put("code",doccode) ;
					mapObj.put("desc",docname) ;
					docResultMap = fileUploadFacade.processCodeAndDesc(mapObj,(Map<String,Object>)initMap.get("docCodeMap"),(Map<String,Object>)initMap.get("docDescMap"),"doctor");
					setProperty(obj, code, docResultMap.get("code"));
					setProperty(obj, desc, docResultMap.get("desc"));
					setProperty(obj, "id", pmainindex);
				}
			    application.updateDoctorCodeById(obj) ;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	
	/**
	 *  根据处理的实体类拼接sql
	 *  findSqlByDocField.  
	 *  @Description：
	 *  @Author ChenHanlin
	 *  @param code 编码字段
	 *  @param desc 描述字段
	 *  @param dateFrom 开始时间
	 *  @param dateTo 结束时间
	 *  @param entityClass
	 *  @return 
	 *  @Date:2018年3月12日下午3:28:53
	 */
	private String findSqlByDocField (String code,String desc,String dateFrom,String dateTo,String entityClass) {
		// 返回更新首页的SQL
		if("MrIpInfo".equals(entityClass)) {
			StringBuffer ipinfoSQL = new StringBuffer() ;
			ipinfoSQL.append(" select ipinfo.pmainindex id, ipinfo."+code+" doccode,ipinfo."+desc+" docname \n ") ;
			ipinfoSQL.append(" from drgs.mr_ipinfo ipinfo \n ") ;
			ipinfoSQL.append(" where to_char(ipinfo.p00290000,'yyyy-mm-dd') between '"+dateFrom+"' and '"+dateTo+"' and ipinfo."+code+" is null \n ") ;
			return ipinfoSQL.toString();
		} else if("MrOperation".equals(entityClass)) { // 更新医师表
			StringBuffer opeSQL = new StringBuffer() ;
			opeSQL.append(" select ope.id id, ope."+code+" doccode,ope."+desc+" docname \n ") ;
			opeSQL.append(" from drgs.mr_operation ope \n ") ;
			opeSQL.append(" left join drgs.mr_ipinfo ipinfo on ope.pmainindex = ipinfo.pmainindex \n ") ;
			opeSQL.append(" where to_char(ipinfo.p00290000,'yyyy-mm-dd') between '"+dateFrom+"' and '"+dateTo+"' and ope."+code+" is null \n ") ;
			return opeSQL.toString();
		} else {
			return "" ;
		}
	}
}
